package com.sleepycat.je; import java.io.File; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import com.sleepycat.je.txn.Txn; import com.sleepycat.je.txn.TxnManager; import de.ovgu.cide.jakutil.*; /** * Javadoc for this public class is generated * via the doc templates in the doc_src directory. */ public class XAEnvironment extends Environment implements XAResource { private static final boolean DEBUG=false; /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public XAEnvironment( File envHome, EnvironmentConfig configuration) throws DatabaseException { super(envHome,configuration); } /** * Used to get the Transaction object given an XA Xid. */ public Transaction getXATransaction( Xid xid) throws DatabaseException { Txn ret=environmentImpl.getTxnManager().getTxnFromXid(xid); if (ret == null) { return null; } return new Transaction(this,ret); } /** * Used to set the Transaction object for an XA Xid. Public for tests. */ public void setXATransaction( Xid xid, Transaction txn) throws DatabaseException { environmentImpl.getTxnManager().registerXATxn(xid,txn.getTxn(),false); } /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public void commit( Xid xid, boolean ignore) throws XAException { if (DEBUG) { System.out.println("*** commit called " + xid + "/"+ ignore); } if (xid == null) { return; } try { checkEnv(); Transaction txn=getXATransaction(xid); if (txn == null) { throw new XAException("No transaction found for " + xid + " during commit."); } removeReferringHandle(txn); if (txn.getTxn().getOnlyAbortable()) { throw new XAException(XAException.XA_RBROLLBACK); } txn.getTxn().commit(xid); } catch ( DatabaseException DE) { throwNewXAException(DE); } if (DEBUG) { System.out.println("*** commit finished"); } } /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public void end( Xid xid, int flags) throws XAException { if (DEBUG) { System.out.println("*** end called " + xid + "/"+ flags); } boolean tmFail=(flags & XAResource.TMFAIL) != 0; boolean tmSuccess=(flags & XAResource.TMSUCCESS) != 0; boolean tmSuspend=(flags & XAResource.TMSUSPEND) != 0; if ((tmFail && tmSuccess) || ((tmFail || tmSuccess) && tmSuspend)) { throw new XAException(XAException.XAER_INVAL); } try { if (DEBUG) { System.out.println("Transaction for " + Thread.currentThread() + " is "+ environmentImpl.getTxnManager().getTxnForThread()); } Transaction txn=environmentImpl.getTxnManager().unsetTxnForThread(); if (txn == null) { txn=getXATransaction(xid); boolean isSuspended=(txn != null) && txn.getTxn().isSuspended(); if (!isSuspended) { throw new XAException(XAException.XAER_NOTA); } } if (tmFail) { txn.getTxn().setOnlyAbortable(); } if (tmSuspend) { txn.getTxn().setSuspended(true); } } catch ( DatabaseException DE) { throwNewXAException(DE); } } /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public void forget( Xid xid) throws XAException { if (DEBUG) { System.out.println("*** forget called"); } throw new XAException(XAException.XAER_NOTA); } /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public boolean isSameRM( XAResource rm) throws XAException { if (DEBUG) { System.out.println("*** isSameRM called"); } try { checkEnv(); } catch ( DatabaseException DE) { throwNewXAException(DE); } if (rm == null) { return false; } if (!(rm instanceof XAEnvironment)) { return false; } return environmentImpl == DbInternal.envGetEnvironmentImpl((XAEnvironment)rm); } /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public int prepare( Xid xid) throws XAException { if (DEBUG) { System.out.println("*** prepare called"); } try { checkEnv(); Transaction txn=getXATransaction(xid); if (txn == null) { throw new XAException("No transaction found for " + xid + " during prepare."); } txn.getTxn().prepare(xid); if (DEBUG) { System.out.println("*** prepare returning XA_OK"); } return XAResource.XA_OK; } catch ( DatabaseException DE) { throwNewXAException(DE); } return XAResource.XA_OK; } /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public Xid[] recover( int flags) throws XAException { if (DEBUG) { System.out.println("*** recover called"); } boolean tmStartRScan=(flags & XAResource.TMSTARTRSCAN) != 0; boolean tmEndRScan=(flags & XAResource.TMENDRSCAN) != 0; if ((tmStartRScan && tmEndRScan) || (!tmStartRScan && !tmEndRScan && flags != TMNOFLAGS)) { throw new XAException(XAException.XAER_INVAL); } try { checkHandleIsValid(); checkEnv(); if (DEBUG) { System.out.println("*** recover returning1"); } return environmentImpl.getTxnManager().XARecover(); } catch ( DatabaseException DE) { throwNewXAException(DE); } return null; } /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public void rollback( Xid xid) throws XAException { if (DEBUG) { System.out.println("*** rollback called"); } try { checkEnv(); Transaction txn=getXATransaction(xid); if (txn == null) { throw new XAException("No transaction found for " + xid + " during abort."); } removeReferringHandle(txn); txn.getTxn().abort(xid); } catch ( DatabaseException DE) { throwNewXAException(DE); } if (DEBUG) { System.out.println("*** rollback returning"); } } /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public int getTransactionTimeout() throws XAException { try { return (int)((getConfig().getTxnTimeout() + 999999L) / 1000000L); } catch ( Exception DE) { throwNewXAException(DE); } return 0; } /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public boolean setTransactionTimeout( int timeout) throws XAException { return false; } /** * Javadoc for this public method is generated via * the doc templates in the doc_src directory. */ public void start( Xid xid, int flags) throws XAException { if (DEBUG) { System.out.println("*** start called " + xid + "/"+ flags); } boolean tmJoin=(flags & XAResource.TMJOIN) != 0; boolean tmResume=(flags & XAResource.TMRESUME) != 0; if (xid == null || (tmJoin && tmResume) || (!tmJoin && !tmResume && flags != XAResource.TMNOFLAGS)) { throw new XAException(XAException.XAER_INVAL); } try { Transaction txn=getXATransaction(xid); TxnManager txnMgr=environmentImpl.getTxnManager(); if (flags == XAResource.TMNOFLAGS) { if (txn == null) { if (DEBUG) { System.out.println("Transaction for XID " + xid + " being created"); } txn=beginTransaction(null,null); setXATransaction(xid,txn); } else { throw new XAException(XAException.XAER_DUPID); } } else if (tmJoin) { if (txn == null) { throw new XAException(XAException.XAER_NOTA); } if (txnMgr.getTxnForThread() != null) { throw new XAException(XAException.XAER_PROTO); } } else if (tmResume) { if (txn == null) { throw new XAException(XAException.XAER_NOTA); } if (!txn.getTxn().isSuspended()) { throw new XAException(XAException.XAER_PROTO); } txn.getTxn().setSuspended(false); } if (DEBUG) { System.out.println("Setting Transaction for " + Thread.currentThread()); } txnMgr.setTxnForThread(txn); } catch ( DatabaseException DE) { if (DEBUG) { System.out.println("*** start exception"); } throwNewXAException(DE); } if (DEBUG) { System.out.println("*** start finished"); } } private void throwNewXAException( Exception E) throws XAException { XAException ret=new XAException(E.toString()); ret.initCause(E); throw ret; } }